package com.wzk.canalsync.loader;

import com.wzk.canalsync.canal.CanalClient;
import com.wzk.canalsync.utils.LogToFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;

/**
    @author wangzikang
*/
@Slf4j
//暂时还使用不了 jar包中无法加载类
//@Component
public class TemplateClassLoader {

    //模板类容器
    private static final ConcurrentHashMap<String,Class<?>> classMap = new ConcurrentHashMap<>();

    public static final Logger logger = Logger.getLogger(TemplateClassLoader.class.getName());

    //获取模板的class
    public static Class<?> getTemplateClass(String className) throws ClassNotFoundException {
        try {
           return classMap.get(className);
        }catch (Exception e) {
            log.error("TemplateClassLoader中出现异常：{}",e.getMessage());
            throw new ClassNotFoundException("找不到这个类"+e);
        }
    }

//    @PostConstruct
    public void loadTemplate() {
        log.info("开始加载模板类！路径：com.wzk.canalsync.template");
        try {
            //需要加载的包路径
            String packageName = "com.wzk.canalsync.template";
            getClassesFromPackage(packageName);
            log.info("加载完成！templateMap:{}",classMap);
        }catch (Exception e) {
            log.error("模板加载出现异常！异常：{}",e.getMessage());
            LogToFile.logToFile("模板加载出现异常！异常："+e.getMessage(),logger,"template_load_err");
        }
    }

    /**
     * 从指定包路径加载所有类
     */
    public static void getClassesFromPackage(String packageName) {
        try {
            // 将包路径转换为文件路径
            String path = packageName.replace('.', '/');
            URL resource = Thread.currentThread().getContextClassLoader().getResource(path);

            if (resource == null) {
                throw new ClassNotFoundException("指定的包路径不存在: " + packageName);
            }
            // 如果资源路径是文件夹
            if ("file".equals(resource.getProtocol())) {
                log.info("从资源文件夹中加载...");
                File directory = new File(resource.toURI());
                if (directory.exists() && directory.isDirectory()) {
                    // 获取该目录下所有的类文件
                    File[] files = directory.listFiles((dir, name) -> name.endsWith(".class"));
                    for (File file : files) {
                        String className = file.getName().replace(".class", "");
                        // 通过类加载器加载类
                        Class<?> clazz = Class.forName(packageName + "." + className);
                        classMap.put(className, clazz);
                    }
                } else {
                    throw new ClassNotFoundException("无法访问目录: " + path);
                }
                //TODO 这里还是无法从jar包中加载类
            } else if ("jar".equals(resource.getProtocol())) {
                // 如果是 JAR 文件中的资源
                String jarFilePath = resource.getPath();
                if (jarFilePath.startsWith("file:")) {
                    jarFilePath = jarFilePath.substring("file:".length());
                }

                // 处理 JAR 文件路径中的 `!` 和实际文件路径
                String jarFilePathWithoutProtocol = jarFilePath.substring(0, jarFilePath.indexOf("!"));
                String jarEntryPath = jarFilePath.substring(jarFilePath.indexOf("!") + 2);

                // 从 JAR 文件中读取文件
                try (JarFile jarFile = new JarFile(jarFilePathWithoutProtocol)) {
                    Enumeration<JarEntry> entries = jarFile.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        // 只处理当前包中的类文件
                        if (entry.getName().startsWith(jarEntryPath) && entry.getName().endsWith(".class")) {
                            String className = entry.getName().replace("/", ".").replace(".class", "");
                            // 通过类加载器加载类
                            Class<?> clazz = Class.forName(className);
                            classMap.put(className, clazz);
                        }
                    }
                } catch (IOException e) {
                    log.error("从 JAR 文件加载类时出现错误: {}", e.getMessage());
                }
            }
            else {
                throw new ClassNotFoundException("无法访问目录: " + path);
            }
        } catch (Exception e) {
            log.error("getClassesFromPackage方法出现异常！ex:{}",e.getMessage());
            e.printStackTrace();
        }
    }
}
